package testing.module;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.KeyEvent;
//import java.util.ArrayList;
import java.util.Properties;
import java.util.Random;

import utilities.display.shapes.definedshapes.DrawPolygon;
import utilities.module.Module;

/**
 * 
 * @author CoconutTank
 *
 */
public class CanyonWalls extends Module
{
	/**
	 * 
	 */
	private static final long serialVersionUID = -6452757132849399124L;

	//protected ArrayList<DrawPolygon> leftWall;
	//protected ArrayList<DrawPolygon> rightWall;
	
	protected DrawPolygon leftWall;
	protected DrawPolygon rightWall;
	
	protected int totalLeftWallLength;
	protected int totalRightWallLength;
	
	protected final int MIN_LENGTH = 10;
	protected final int MAX_LENGTH = 100;
	
	protected int maxLength;
	
	protected final int MIN_DEPTH = 1;
	protected final int MAX_DEPTH_CHANGE = 50;

	protected int lastLeftDepth;
	protected int lastRightDepth;
	
	protected int maxLeftDepth;
	protected int maxRightDepth;
	
	protected int screenWidth;
	protected int screenHeight;
	
	protected final int MIN_OPEN_SPACE = 31;
	protected final int MAX_OPEN_SPACE;
	
	protected int distanceTravelled;
	
	protected Random rand;
	
	protected boolean moveLeft;
	protected boolean moveRight;
	protected boolean moveUp;
	protected boolean moveDown;
	
	public CanyonWalls()
	{
		//leftWall = new ArrayList<DrawPolygon>();
		//rightWall = new ArrayList<DrawPolygon>();
		
		leftWall = new DrawPolygon(Color.black, null, null, Color.black, null);
		rightWall = new DrawPolygon(Color.black, null, null, Color.black, null);
		
		maxLength = 20000;
		
		lastLeftDepth = 10;
		lastRightDepth = 10;
		
		screenWidth = 500;
		screenHeight = 700;
		
		distanceTravelled = 0;
		
		totalLeftWallLength = 0;
		totalRightWallLength = 0;
		
		rand = new Random();
		
		MAX_OPEN_SPACE = screenWidth;
		
		maxLeftDepth = maxRightDepth = (MAX_OPEN_SPACE - MIN_OPEN_SPACE) / 2;
		
		createCanyonWalls();
		
		/*
		leftWall.addPoint(0, 0);
		leftWall.addPoint(20, 0);
		leftWall.addPoint(20, 20);
		leftWall.addPoint(0, 20);
		*/
	}

	public void drawMe(Graphics g) 
	{
		Graphics2D g2 = (Graphics2D)g;
		
		//g2.setColor(Color.black);
		//g2.drawRect(100, 100, 100, 100);
		
		//g2.draw(leftWall.getShape());
		leftWall.drawMe(g2);
		rightWall.drawMe(g2);
	}

	public void keyPressed(KeyEvent e) 
	{
		if(e.getKeyCode() == KeyEvent.VK_UP
		   || e.getKeyCode() == KeyEvent.VK_W)
		{
			moveUp = true;
		}
		
		if(e.getKeyCode() == KeyEvent.VK_DOWN
		   || e.getKeyCode() == KeyEvent.VK_S)
		{
			moveDown = true;
		}

		if(e.getKeyCode() == KeyEvent.VK_LEFT
		   || e.getKeyCode() == KeyEvent.VK_A)
		{
			moveLeft = true;
		}

		if(e.getKeyCode() == KeyEvent.VK_RIGHT
		   || e.getKeyCode() == KeyEvent.VK_D)
		{
			moveRight = true;
		}
	}

	public void keyReleased(KeyEvent e) 
	{
		if(e.getKeyCode() == KeyEvent.VK_UP
		   || e.getKeyCode() == KeyEvent.VK_W)
		{
			moveUp = false;
		}
		
		if(e.getKeyCode() == KeyEvent.VK_DOWN
		   || e.getKeyCode() == KeyEvent.VK_S)
		{
			moveDown = false;
		}

		if(e.getKeyCode() == KeyEvent.VK_LEFT
		   || e.getKeyCode() == KeyEvent.VK_A)
		{
			moveLeft = false;
		}

		if(e.getKeyCode() == KeyEvent.VK_RIGHT
		   || e.getKeyCode() == KeyEvent.VK_D)
		{
			moveRight = false;
		}
	}

	public void update(Properties globals) 
	{
		// Automatically move the walls
		/*
		if(moveUp)
		{
			leftWall.translate(0, 20);
			rightWall.translate(0, 20);
			//System.out.println("up!");
		}
		
		if(moveDown)
		{
			leftWall.translate(0, -20);
			rightWall.translate(0, -20);
			//System.out.println("down!");
		}
		*/
		
		leftWall.translate(0, 5);
		rightWall.translate(0, 5);
	}
	
	public void createCanyonWalls()
	{
		// Each side of the canyon must be as long as the track itself.
		// Each side of the canyon starts at the left and right corners.
		
		leftWall.addPoint(0, 0);
		rightWall.addPoint(screenWidth, 0);
		
		// Randomly generate points for each side until both walls fill the entire race length.
		//while(leftWallLength < maxLength)
		while(totalLeftWallLength < maxLength || totalRightWallLength < maxLength)
		{
			// Determine length of the corridor
			int wallLength = rand.nextInt(MAX_LENGTH - MIN_LENGTH + 1) + MIN_LENGTH;
			
			// Continue building the left wall if there is enough space left
			if(totalLeftWallLength < maxLength)
			{
				// Record remaining wall length
				int remainingLeftWallLength = wallLength;
				
				// For each point...
				while(remainingLeftWallLength >= MIN_LENGTH)
				{
					// Determine length of random corridor point
					int currLeftWallLength = rand.nextInt(Math.max(remainingLeftWallLength - MIN_LENGTH + 1, 1)) + MIN_LENGTH;
					
					// Determine depth of random corridor point
					lastLeftDepth = Math.min(maxLeftDepth, Math.max(MIN_DEPTH, lastLeftDepth + rand.nextInt(MAX_DEPTH_CHANGE) - rand.nextInt(MAX_DEPTH_CHANGE)));
					
					// Add new corridor point to the left wall
					leftWall.addPoint(lastLeftDepth, -(totalLeftWallLength + currLeftWallLength));
					
					// Increase left wall length to new length of progress
					totalLeftWallLength += currLeftWallLength;
					
					// Subtract left length used from remaining left wall length
					remainingLeftWallLength -= currLeftWallLength;
				}
			}
			
			// Continue building the right wall if there is enough space left
			if(totalRightWallLength < maxLength)
			{
				// Record remaining wall length
				int remainingRightWallLength = wallLength;
				
				// For each point...
				while(remainingRightWallLength >= MIN_LENGTH)
				{
					// Determine length of random corridor
					int currRightWallLength = rand.nextInt(Math.max(remainingRightWallLength - MIN_LENGTH + 1, 1)) + MIN_LENGTH;
					
					// Determine depth of random corridor
					lastRightDepth = Math.min(maxRightDepth, Math.max(MIN_DEPTH, lastRightDepth + rand.nextInt(MAX_DEPTH_CHANGE) - rand.nextInt(MAX_DEPTH_CHANGE)));
	
					// Add new "points" of corridor to the right wall
					rightWall.addPoint(screenWidth - lastRightDepth, -(totalRightWallLength + currRightWallLength));
					
					// Increase left wall length to new length of progress
					totalRightWallLength += currRightWallLength;
					
					// Subtract left length used from remaining left wall length
					remainingRightWallLength -= currRightWallLength;
				}
			}
			
			// Shift available area to the left or right by a small amount
			int corridorShift = rand.nextInt(5) * (rand.nextBoolean() ? 1 : -1);
			
			maxLeftDepth += corridorShift;
			maxRightDepth -= corridorShift;
			
			// Make sure possible depths stay within boundaries
			if(maxLeftDepth > screenWidth - MIN_OPEN_SPACE) maxLeftDepth = screenWidth - MIN_OPEN_SPACE;
			else if(maxLeftDepth < MIN_DEPTH) maxLeftDepth = MIN_DEPTH;

			if(maxRightDepth > screenWidth - MIN_OPEN_SPACE) maxRightDepth = screenWidth - MIN_OPEN_SPACE;
			else if(maxRightDepth < MIN_DEPTH) maxRightDepth = MIN_DEPTH;
		}
		
		// Last point of each wall should be MAX_LENGTH after supposed max distance
		leftWall.addPoint(0, -(maxLength + MAX_LENGTH));
		rightWall.addPoint(screenWidth, -(maxLength + MAX_LENGTH));
	}
}
